Popular Searches
Popular Course Categories
Popular Courses

Introduction to the Java Collections Framework

Introduction to the Java Collections Framework

Java Collections Framework

Introduction to the Java Collections Framework

Course: Core Java Training

Topic: Introduction to the Java Collections Framework

Course URL: https://www.justacademy.co/course-detail/core-java-training

Demo URL: Register for a Course Demo

Website: JustAcademy Official Website


1. Introduction to the Java Collections Framework

The Java Collections Framework (JCF) is a standard set of interfaces, classes, and algorithms used to store, organize, access, and manipulate groups of objects. It provides reusable data structures such as lists, sets, queues, and maps, helping developers manage data without implementing every data structure from scratch.

For example, an online shopping application might use a list to display products, a set to store unique product categories, a queue to process orders, and a map to associate product IDs with product details.

Why Do We Need Collections?

  • To store and manage multiple objects efficiently.
  • To add or remove elements dynamically when supported by the implementation.
  • To search, sort, and retrieve data using standard methods.
  • To avoid repeatedly writing custom data structures.
  • To improve code reuse, readability, and maintainability.
  • To select a data structure based on ordering, uniqueness, and performance requirements.

2. Learning Objectives

After completing this topic, learners should be able to:

  • Define the Java Collections Framework and explain its purpose.
  • Understand the difference between interfaces, implementations, and utility classes.
  • Explain the roles of List, Set, Queue, Deque, and Map.
  • Use common collection classes in Java programs.
  • Understand generics and type safety.
  • Perform basic collection operations such as adding, removing, searching, and iterating.
  • Choose a suitable collection for a given programming requirement.

3. What Is a Collection in Java?

A collection is an object that represents a group of elements. In the Java Collections Framework, most collection implementations store references to objects and provide methods to manipulate those elements.

Suppose a program needs to store several student names. Instead of declaring a separate variable for every student, a collection can keep all the names together.

Example

import java.util.ArrayList;
import java.util.List;

public class StudentExample {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();

        students.add("Aarav");
        students.add("Priya");
        students.add("Rahul");

        System.out.println(students);
    }
}

Output:

[Aarav, Priya, Rahul]

Here, List is an interface, ArrayList is an implementation, and students is a variable referring to the created collection.

4. What Is the Java Collections Framework?

The Java Collections Framework provides a unified architecture for representing and manipulating groups of objects. It consists of the following major components:

  • Interfaces: Define the operations available on different types of data structures.
  • Implementations: Concrete classes that provide the actual data-storage behavior.
  • Algorithms: Operations such as sorting, searching, reversing, and shuffling.
  • Utility methods: Helper methods for working with collections.
  • Concurrent collections: Implementations designed for particular multithreaded use cases.

The framework separates an interface's behavior from its implementation. For example, a variable declared as List<String> can refer to an ArrayList<String> or a LinkedList<String>, depending on the application's requirements.

5. Advantages of the Collections Framework

Advantage Explanation
Code reusability Developers can use established data structures instead of implementing them repeatedly.
Dynamic sizing Many implementations can grow or shrink as elements are added or removed.
Standard methods Common operations are available through familiar interfaces and methods.
Type safety Generics help prevent incompatible element types from being added.
Flexibility Implementations can be changed while keeping interface-based code largely unchanged.
Algorithms Utility methods simplify tasks such as sorting and reversing lists.
Maintainability Standard interfaces make code easier to understand and modify.

6. Collections Framework Architecture

The framework contains several interfaces and implementing classes. The Iterable interface supports traversal. The Collection interface extends Iterable and is the parent of interfaces such as List, Set, and Queue. The Map interface belongs to the framework but does not extend Collection.

Iterable
   |
Collection
   |-----------------------------|
   |              |              |
  List            Set           Queue
   |              |              |
ArrayList       HashSet       PriorityQueue
LinkedList      LinkedHashSet ArrayDeque*
Vector          TreeSet       LinkedList*

Map
 |
 |-- HashMap
 |-- LinkedHashMap
 |-- TreeMap
 |-- Hashtable

* ArrayDeque implements Deque, which extends Queue.
  LinkedList implements List and Deque.

This is a simplified overview rather than a complete inheritance diagram. The framework also contains interfaces such as SortedSet, NavigableSet, SortedMap, and concurrent collection interfaces.

7. The Iterable Interface

The Iterable<T> interface represents an object whose elements can be visited one at a time. It provides the iterator() method and enables the enhanced for loop.

Example

import java.util.ArrayList;
import java.util.List;

public class IterableExample {
    public static void main(String[] args) {
        List<String> languages = new ArrayList<>();

        languages.add("Java");
        languages.add("Python");
        languages.add("JavaScript");

        for (String language : languages) {
            System.out.println(language);
        }
    }
}

Output:

Java
Python
JavaScript

8. The Collection Interface

The Collection<E> interface defines common operations for groups of elements. Many collection implementations support the following methods, although certain unmodifiable implementations may reject modification operations.

Method Purpose
add(E element) Adds an element when supported.
addAll(Collection c) Adds elements from another collection when supported.
remove(Object o) Removes a matching element when supported.
contains(Object o) Checks whether an element is present.
size() Returns the number of elements.
isEmpty() Checks whether the collection contains no elements.
clear() Removes all elements when supported.
iterator() Returns an iterator for traversal.
toArray() Converts the collection's elements into an array.

9. Understanding the List Interface

The List interface represents an ordered collection. It supports positional access through indexes and generally permits duplicate elements. Indexing begins at zero.

Common List Implementations

Class Characteristics Typical Use
ArrayList Resizable array; efficient index-based access. General-purpose lists and frequent reads by index.
LinkedList Doubly linked structure; implements List and Deque. Sequential traversal and deque operations.
Vector Legacy resizable array with synchronized methods. Maintaining older applications that use Vector.
Stack Legacy LIFO stack class based on Vector. Legacy code; ArrayDeque is generally preferred for new stack use.

Example: ArrayList

import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();

        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        fruits.add("Apple");

        System.out.println(fruits);
        System.out.println(fruits.get(1));

        fruits.set(1, "Orange");
        fruits.remove("Mango");

        System.out.println(fruits);
    }
}

Output:

[Apple, Banana, Mango, Apple]
Banana
[Apple, Orange, Apple]

The example demonstrates adding elements, retrieving an element by index, replacing an element, and removing a matching value.

10. Understanding the Set Interface

The Set interface represents a collection that does not permit duplicate elements according to its equality rules. The iteration order depends on the implementation.

Class Ordering Use Case
HashSet No guaranteed iteration order. Storing unique values and checking membership.
LinkedHashSet Preserves insertion order. Unique values in insertion order.
TreeSet Maintains sorted order. Unique values that need sorting.

Example: HashSet

import java.util.HashSet;
import java.util.Set;

public class SetExample {
    public static void main(String[] args) {
        Set<String> cities = new HashSet<>();

        cities.add("Mumbai");
        cities.add("Pune");
        cities.add("Delhi");
        cities.add("Mumbai");

        System.out.println(cities);
        System.out.println("Unique cities: " + cities.size());
    }
}

Sample output:

[Mumbai, Pune, Delhi]
Unique cities: 3

The order in this sample output is illustrative only. A HashSet does not guarantee iteration order.

11. Understanding the Queue Interface

The Queue interface is used to hold elements before processing. Many queues follow FIFO (First In, First Out) order, although priority queues use a priority-based ordering policy.

Method Purpose Failure Behavior
offer(e) Attempts to insert an element. May return false if insertion is not possible.
add(e) Inserts an element. May throw an exception if insertion fails.
poll() Removes and returns the head. Returns null if the queue is empty.
remove() Removes and returns the head. Throws an exception if the queue is empty.
peek() Examines the head without removing it. Returns null if the queue is empty.
element() Examines the head without removing it. Throws an exception if the queue is empty.

Example: Queue

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {
        Queue<String> orders = new LinkedList<>();

        orders.offer("Order 101");
        orders.offer("Order 102");
        orders.offer("Order 103");

        System.out.println(orders.peek());
        System.out.println(orders.poll());
        System.out.println(orders);
    }
}

Output:

Order 101
Order 101
[Order 102, Order 103]

12. Understanding the Deque Interface

Deque stands for double-ended queue. It supports inserting and removing elements from both ends. It can be used as either a FIFO queue or a LIFO stack.

ArrayDeque is a common implementation and is generally preferred over the legacy Stack class for new stack operations. It does not permit null elements.

Example: Using ArrayDeque as a Stack

import java.util.ArrayDeque;
import java.util.Deque;

public class StackExample {
    public static void main(String[] args) {
        Deque<String> stack = new ArrayDeque<>();

        stack.push("First");
        stack.push("Second");
        stack.push("Third");

        System.out.println(stack.pop());
        System.out.println(stack.peek());
    }
}

Output:

Third
Second

13. Understanding the Map Interface

The Map interface stores key-value pairs. Each key can appear only once, while different keys can contain equal values. If a key is inserted again, its previous value is replaced.

Class Characteristics Use Case
HashMap No guaranteed iteration order. General key-value storage and lookups.
LinkedHashMap Normally preserves insertion order; can also be configured for access order. Predictable iteration order or cache-related designs.
TreeMap Sorts entries by keys. Sorted key access and range operations.
Hashtable Legacy synchronized map implementation. Legacy code; alternatives are generally preferred for new development.

Example: Student Marks

import java.util.HashMap;
import java.util.Map;

public class MapExample {
    public static void main(String[] args) {
        Map<String, Integer> marks = new HashMap<>();

        marks.put("Aarav", 85);
        marks.put("Priya", 92);
        marks.put("Rahul", 78);

        System.out.println(marks.get("Priya"));

        marks.put("Aarav", 90);

        System.out.println(marks.containsKey("Rahul"));
        System.out.println(marks);
    }
}

Output:

92
true
{Aarav=90, Priya=92, Rahul=78}

The displayed order is not guaranteed for a HashMap. The updated mark for Aarav replaces the earlier value associated with the same key.

Important Map Methods

  • put(key, value) adds or updates a mapping.
  • get(key) retrieves a value for a key.
  • getOrDefault(key, defaultValue) returns a default value when the key is not mapped.
  • containsKey(key) checks whether a key is present.
  • containsValue(value) checks whether a value is present.
  • remove(key) removes a mapping.
  • keySet() provides a set view of the keys.
  • values() provides a collection view of the values.
  • entrySet() provides a set view of the key-value entries.

14. Difference Between Collection and Map

Feature Collection Map
Data organization Stores individual elements. Stores key-value mappings.
Core interface Collection<E> Map<K,V>
Duplicates Depends on the collection type. Keys are unique; values can repeat.
Examples ArrayList, HashSet HashMap, TreeMap
Common methods add(), remove(), contains() put(), get(), containsKey()

A Map belongs to the Collections Framework but is not a subtype of the Collection interface.

15. Arrays vs. Collections

Feature Array Collection
Size Fixed after creation. Many implementations support dynamic sizing.
Primitive values Can store primitives directly. Standard generic collections store objects; wrapper classes represent primitive values.
Operations Uses indexes and array utilities. Provides methods for common data operations.
Type safety Enforced by the array's component type. Generics provide compile-time type checking.
Best suited for Fixed-size data and primitive arrays. Flexible groups of objects and richer data operations.

Array Example

String[] names = {"Aarav", "Priya", "Rahul"};
System.out.println(names[0]);

Collection Example

List<String> names = new ArrayList<>();
names.add("Aarav");
names.add("Priya");
names.add("Rahul");
names.add("Meera");

System.out.println(names.get(0));
System.out.println(names.size());

16. Generics in the Collections Framework

Generics allow developers to specify the type of elements a collection can store. They improve compile-time type safety and reduce the need for explicit casting.

Example Using Generics

import java.util.ArrayList;
import java.util.List;

public class GenericsExample {
    public static void main(String[] args) {
        List<String> languages = new ArrayList<>();

        languages.add("Java");
        languages.add("Python");

        // languages.add(100); // Compile-time error

        for (String language : languages) {
            System.out.println(language);
        }
    }
}

Since the list is declared as List<String>, the compiler prevents incompatible values such as integers from being added. Use wrapper types such as Integer, Double, and Boolean instead of primitive types as generic type arguments.

17. Common Collection Operations

import java.util.ArrayList;
import java.util.List;

public class CollectionOperations {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();

        numbers.add(10);
        numbers.add(20);
        numbers.add(30);

        System.out.println("Size: " + numbers.size());
        System.out.println("Contains 20: " + numbers.contains(20));

        numbers.remove(Integer.valueOf(20));

        for (Integer number : numbers) {
            System.out.println(number);
        }

        numbers.clear();
        System.out.println("Empty: " + numbers.isEmpty());
    }
}

Output:

Size: 3
Contains 20: true
10
30
Empty: true

Important: In a List<Integer>, remove(1) refers to the element at index 1. To remove the integer value 1, use remove(Integer.valueOf(1)).

18. Iterating Through Collections

Iteration means processing elements one at a time. Java supports enhanced for loops, iterators, and other traversal techniques.

18.1 Enhanced For Loop

List<String> subjects = List.of("Java", "SQL", "Python");

for (String subject : subjects) {
    System.out.println(subject);
}

18.2 Iterator

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(
            List.of("Aarav", "Priya", "Rahul")
        );

        Iterator<String> iterator = names.iterator();

        while (iterator.hasNext()) {
            String name = iterator.next();

            if (name.equals("Rahul")) {
                iterator.remove();
            }
        }

        System.out.println(names);
    }
}

Output:

[Aarav, Priya]

When removing elements during iteration, use the iterator's remove() method where supported. Direct structural changes to many collections during a for-each loop may cause a ConcurrentModificationException.

18.3 Iterating Through a Map

Map<String, Integer> scores = new HashMap<>();
scores.put("Aarav", 85);
scores.put("Priya", 92);

for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

19. Sorting and the Collections Utility Class

The Collections class contains static utility methods for common collection operations. It is different from the Collection interface.

Method Purpose
Collections.sort(list) Sorts a list by natural ordering.
Collections.reverse(list) Reverses the current list order.
Collections.shuffle(list) Randomly rearranges list elements.
Collections.max(collection) Finds the maximum element according to ordering.
Collections.min(collection) Finds the minimum element according to ordering.
Collections.frequency(collection, value) Counts occurrences of a value.

Example

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SortingExample {
    public static void main(String[] args) {
        List<Integer> numbers =
            new ArrayList<>(List.of(40, 10, 30, 20));

        Collections.sort(numbers);
        System.out.println(numbers);

        Collections.reverse(numbers);
        System.out.println(numbers);

        System.out.println(Collections.max(numbers));
        System.out.println(Collections.frequency(numbers, 20));
    }
}

Output:

[10, 20, 30, 40]
[40, 30, 20, 10]
40
1

20. Choosing the Right Collection

Requirement Suggested Type Reason
Frequent access by index ArrayList Efficient index-based access.
Unique values without ordering needs HashSet Prevents duplicates and supports membership checks.
Unique values in insertion order LinkedHashSet Maintains insertion order.
Unique sorted values TreeSet Maintains sorted set order.
Key-value lookups HashMap General-purpose map implementation.
Sorted keys TreeMap Maintains mappings in key order.
Queue or stack operations ArrayDeque Supports operations at both ends.
Concurrent key-value access ConcurrentHashMap Designed for concurrent access.

These recommendations are general guidelines. The best choice depends on the application's data size, ordering requirements, access patterns, concurrency needs, and measured performance.

21. Immutable and Unmodifiable Collections

Some collections do not permit changes after creation. Factory methods such as List.of(), Set.of(), and Map.of() create unmodifiable collections or maps.

import java.util.List;

public class UnmodifiableExample {
    public static void main(String[] args) {
        List<String> languages = List.of("Java", "Python");

        System.out.println(languages);

        // languages.add("SQL");
        // Throws UnsupportedOperationException
        // if executed.
    }
}

These factory-created collections reject null elements and do not support structural modification. An unmodifiable collection is not necessarily deeply immutable if it contains mutable objects.

The method Collections.unmodifiableList(existingList) creates an unmodifiable view of another list. Changes made through the original list may still be visible through that view.

22. Thread Safety and Concurrent Collections

Ordinary implementations such as ArrayList and HashMap do not make arbitrary concurrent modifications safe. When multiple threads share mutable data, developers must choose an appropriate synchronization strategy.

  • ConcurrentHashMap supports concurrent access to mappings.
  • CopyOnWriteArrayList can suit workloads with frequent reads and relatively infrequent writes.
  • Collections.synchronizedList() provides synchronized access through a wrapper, but iteration and compound operations still require care.

Thread-safe individual methods do not automatically make a sequence of multiple operations atomic. Select concurrent data structures according to the requirements of the application.

23. Common Errors and Troubleshooting

Error or Problem Cause Solution
ClassCastException Incompatible casting, often involving raw collections. Use generics and avoid unnecessary casts.
UnsupportedOperationException Attempting a prohibited modification. Use a mutable implementation if modifications are needed.
ConcurrentModificationException A fail-fast iterator detects an unsupported structural modification. Use the iterator's removal operation or another suitable approach.
Unexpected Set behavior Custom objects have unsuitable equality or hashing behavior. Implement equals() and hashCode() consistently.
Unexpected iteration order The chosen implementation does not guarantee the required order. Use an ordered or sorted implementation.
Unexpected Map value An existing key was mapped to a new value. Check the key and update logic.

24. Best Practices

  • Prefer interface-based declarations such as List<String> over unnecessarily exposing implementation details.
  • Use generics instead of raw collection types.
  • Select a collection based on ordering, uniqueness, access, and modification requirements.
  • Use a Set when duplicate values must be excluded.
  • Use a Map when values need to be retrieved through keys.
  • Never rely on the iteration order of HashSet or HashMap.
  • Understand whether a collection is mutable, unmodifiable, fixed-size, or a view.
  • Use appropriate iterator methods when removing elements during traversal.
  • Implement equals() and hashCode() consistently for custom objects used in hash-based collections.
  • Use concurrent collections or synchronization when shared mutable state requires it.
  • Use meaningful variable names and test important edge cases.

25. Practical Mini Project: Student Course Manager

Objective: Build a simple Java program that stores student names, keeps course names unique, and maps students to their marks.

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class StudentCourseManager {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();
        students.add("Aarav");
        students.add("Priya");
        students.add("Rahul");

        Set<String> courses = new LinkedHashSet<>();
        courses.add("Java");
        courses.add("SQL");
        courses.add("Java");
        courses.add("Python");

        Map<String, Integer> marks = new HashMap<>();
        marks.put("Aarav", 85);
        marks.put("Priya", 92);
        marks.put("Rahul", 78);

        System.out.println("Students:");
        for (String student : students) {
            System.out.println(student);
        }

        System.out.println("Unique courses: " + courses);
        System.out.println("Priya's marks: " + marks.get("Priya"));
    }
}

Expected Learning Outcomes

  • Use a List to store student names in insertion order.
  • Use a Set to prevent duplicate course names.
  • Use a Map to associate student names with marks.
  • Use a loop to process collection elements.
  • Retrieve a value using a key.

Project Extensions

  • Add operations to register and remove students.
  • Validate marks to ensure they fall between 0 and 100.
  • Display student names alphabetically.
  • Find the highest score and the student who earned it.
  • Handle missing student names during lookups.

26. Practice Exercises

  1. Create an ArrayList of ten integers and print only the even numbers.
  2. Store five city names in a HashSet and check whether a given city exists.
  3. Compare the iteration behavior of HashSet and LinkedHashSet.
  4. Use TreeSet to display unique numbers in sorted order.
  5. Create a HashMap containing employee IDs and names.
  6. Implement a queue to process customer requests in order.
  7. Sort a list of names alphabetically.
  8. Remove a particular integer value from a list without confusing the value with an index.
  9. Iterate through a map using entrySet() and display each key-value pair.
  10. Create a library catalogue using a List for book titles, a Set for unique categories, and a Map for book IDs and titles.

27. Interview Questions and Answers

Q1. What is the Java Collections Framework?

Answer: It is a unified architecture of interfaces, implementations, and algorithms for representing and manipulating groups of objects.

Q2. What is the difference between Collection and Collections?

Answer: Collection is an interface representing a group of elements. Collections is a utility class that provides static methods for operations such as sorting, reversing, and creating unmodifiable wrappers.

Q3. What is the difference between List and Set?

Answer: A List is ordered and generally allows duplicate elements. A Set does not permit duplicate elements and may or may not guarantee a particular order.

Q4. Why is Map not a subtype of Collection?

Answer: A Map stores key-value mappings rather than individual elements. It provides separate operations and collection views for its keys, values, and entries.

Q5. What is the difference between ArrayList and LinkedList?

Answer: ArrayList uses a resizable array and provides efficient index-based access. LinkedList uses a doubly linked structure and also supports deque operations. Their performance depends on the operations performed.

Q6. How does HashSet prevent duplicate values?

Answer: It uses hashing and equality checks to determine whether an equivalent element already exists. Custom objects should implement equals() and hashCode() consistently.

Q7. Can a HashMap contain duplicate keys?

Answer: No. A key can have at most one mapping. Inserting the same key again replaces its previous value.

Q8. What are generics?

Answer: Generics allow collection types to specify the type of elements, keys, or values, improving compile-time type safety.

Q9. What is the difference between Queue and Deque?

Answer: Queue provides operations for processing elements according to a queue's ordering policy. Deque supports insertion and removal at both ends.

Q10. What is ConcurrentModificationException?

Answer: It can occur when a fail-fast iterator detects structural modification outside the iterator's supported operations. It is not a guarantee of thread safety.

Q11. How can a list be sorted?

Answer: Use Collections.sort(list) or list.sort(comparator), depending on the desired ordering.

Q12. Which collection stores unique sorted values?

Answer: TreeSet is a common choice for unique elements maintained in sorted order.

28. Quick Revision Checklist

  • Collection: A group of elements.
  • List: Ordered elements with positional access and generally permits duplicates.
  • Set: Unique elements.
  • Queue: Holds elements before processing.
  • Deque: Supports operations at both ends.
  • Map: Stores unique keys associated with values.
  • ArrayList: Resizable array implementation.
  • HashSet: Unique elements without guaranteed iteration order.
  • HashMap: General-purpose key-value mappings without guaranteed iteration order.
  • TreeSet and TreeMap: Maintain sorted elements or keys.
  • Generics: Improve compile-time type safety.
  • Collections: Utility class for common collection algorithms and wrappers.
  • Iterator: Supports element traversal and removal where permitted.

29. Conclusion

The Java Collections Framework is an essential part of Core Java because it provides standard tools for organizing, storing, and processing data. Understanding the differences between List, Set, Queue, Deque, and Map helps developers choose suitable data structures for real-world applications.

Practise with ArrayList, HashSet, HashMap, and ArrayDeque, then progress to sorting, custom object comparison, iterators, and concurrent collections. These concepts are useful for Java development, application design, and technical interviews.

30. Additional Learning Resources


End of Notes: Introduction to the Java Collections Framework

Previous Next
whatsapp